//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include "pseudo.h"
#include "cevent.h"
#include "cmutex.h"
#include "ccondition.h"
#include "crwlock.h"
#include "cthread.h"
#include "pprocess.h"
#include "cprocess.h"
#include "cmodule.h"
#include "pcentral.h"
#include "pobjenum.h"
#include "pobject.h"
#include "namedobj.h"
#include "namedmutex.h"
#include "namedevent.h"
#include "namedcondition.h"
#include "sharedmem.h"
#include "dhostmgr.h"
#include <aura.h>
#include <elacs.h>
#include "helper.h"

#define INVALID_TLS_INDEX     ((UInt32)-1)

#define _PAGE_SIZE          (1u << 12)
#define IS_PAGE_ALIGNED(va) (0 == ((va) & (_PAGE_SIZE -1)))

// =========== Helper Functions. ====================================
STATIC IProcess *s_pCurrentProcess  = NULL;
STATIC ProcessId s_currentProcessId = AURA_INVALID_PID;
STATIC IThread  *s_pMainThread      = NULL;
UInt32    s_tlsCurrentThreadIndex = INVALID_TLS_INDEX;

#define GetProcess() (static_cast<CProcess *>(s_pCurrentProcess))

static IDeviceDriver * g_pIRTC = NULL;

EXTERN Boolean IsMainThread(
    /* [in]  */ IThread * pThread)
{
    assert(NULL != s_pMainThread);
    return (s_pMainThread == pThread) ? TRUE : FALSE;
}

EXTERN Boolean IsCurrentThread(
    /* [in]  */ IThread * pThread)
{
    IThread * pCurThread = NULL;

    AuraTls_GetValue((Aura_UInt32)s_tlsCurrentThreadIndex, (Aura_PVoid *)&pCurThread);
    //assert(NULL != pCurThread);
    return (pCurThread && pCurThread == pThread) ? TRUE : FALSE;
}

EXTERN Boolean IsCurrentProcessId(
    /* [in] */ ProcessId processId)
{
    return (s_currentProcessId == processId) ? TRUE : FALSE;
}

STATIC INLINE IThread * GetCurrentThread_Unexpected()
{
    IThread * pThread = NULL;
    assert(INVALID_TLS_INDEX != s_tlsCurrentThreadIndex);
    AuraTls_GetValue((Aura_UInt32)s_tlsCurrentThreadIndex, (Aura_PVoid *)&pThread);

    return pThread;
}

EXTERN IThread * GetCurrentThread_Expected()
{
    IThread * pThread = GetCurrentThread_Unexpected();
    //BUGBUG: NULL in dllmain process detach
    //assert(NULL != pThread);
    return pThread;
}

// ====== Initialization and deinitialization of pseudo kernel.====

EXTERN void InitSystemEventLock();

EXTERN_C ECode CDECL PseudoKernel_Initialize()
{
    ECode ec = NOERROR;

    ec = PseudoCentral_Initialize();
    if (FAILED(ec)) {
        goto ErrorExit;
    }

    s_currentProcessId = AuraProcess_GetCurrentId();
    ec = CProcess::S_Create(&s_pCurrentProcess,
                            &s_pMainThread);
    if (FAILED(ec)) {
        goto ErrorExit;
    }

    ec = AuraTls_Allocate((Aura_UInt32 *)&s_tlsCurrentThreadIndex);
    if (FAILED(ec)) {
        goto ErrorExit;
    }
    ec = AuraTls_SetValue(s_tlsCurrentThreadIndex, (Aura_PVoid)s_pMainThread);
    if (FAILED(ec)) {
        goto ErrorExit;
    }

    ec = GetProcess()->TrySetStartInfo();
    if (FAILED(ec)) {
        goto ErrorExit;
    }

    ec = PseudoObject::S_Initialize();
    if (FAILED(ec)) {
        goto ErrorExit;
    }
    ec = NamedObject::S_Initialize();
    if (FAILED(ec)) {
        goto ErrorExit;
    }
    InitSystemEventLock();

    return NOERROR;

ErrorExit:
    PseudoObject::S_Destroy();

    if (INVALID_TLS_INDEX != s_tlsCurrentThreadIndex) {
        AuraTls_Free(s_tlsCurrentThreadIndex);
        s_tlsCurrentThreadIndex = INVALID_TLS_INDEX;
    }

    if (NULL != s_pMainThread) {
        s_pMainThread->Release();
        s_pMainThread = NULL;
    }
    if (NULL != s_pCurrentProcess) {
        s_pCurrentProcess->Release();
        s_pCurrentProcess = NULL;
    }

    PseudoCentral_Destroy();

    return ec;
}

EXTERN_C void CDECL PseudoKernel_Destroy()
{
    NamedObject::S_Destroy();
    PseudoObject::S_Destroy();

    if (INVALID_TLS_INDEX != s_tlsCurrentThreadIndex) {
        AuraTls_Free((Aura_UInt32)s_tlsCurrentThreadIndex);
        s_tlsCurrentThreadIndex = INVALID_TLS_INDEX;
    }

    if (NULL != s_pMainThread) {
        s_pMainThread->Release();
        s_pMainThread = NULL;
    }

    if (NULL != s_pCurrentProcess) {
        //s_pCurrentProcess->Release();
        delete (CProcess *)s_pCurrentProcess;
        s_pCurrentProcess = NULL;
    }

    PseudoCentral_Destroy();

    return ;
}

EXTERN_C ECode CDECL PseudoKernel_ThreadStartEntry(
    /* [in]  */ PVoid pArg)
{
    IThread *pThread = (IThread *)pArg;
    ECode ec = NOERROR;
    Address usrEntry;
    Address usrArgs;

    ((CThread *)pThread)->GetUserEntry(&usrEntry, &usrArgs);

    ec = AuraTls_SetValue(s_tlsCurrentThreadIndex, (Aura_PVoid)pThread);
    assert(NOERROR == ec);
    return ((PThreadMain)usrEntry)((PVoid)usrArgs);
}

// ------------for time information. -----------
CARAPI CPseudoKernel::System_GetTime(
        /* [out] */ SystemTime * pSystemTime)
{
    if (NULL == pSystemTime) {
        return E_INVALID_ARGUMENT;
    }

    MemoryBuf_<sizeof(SystemTime)> TimeBuf;
    SystemTime * pTime = NULL;
    ECode ec = NOERROR;

    if (NULL == g_pIRTC) {
        ec = CPseudoSyscall::FindRunningObject(L"device:rtc0",
                                         (PInterface *)&g_pIRTC);
        if (FAILED(ec)) return ec;
    }

    ec = g_pIRTC->Control(100, NULL_MEMORYBUF, &TimeBuf, NULL);
    if (FAILED(ec)) {
        return ec;
    }

    pTime = (SystemTime*)(TimeBuf.GetPayload());
    pSystemTime->microseconds = pTime->microseconds;
    pSystemTime->seconds = pTime->seconds;

    return NOERROR;
}

CARAPI CPseudoKernel::System_SetTime(
        /* [in] */ SystemTime * pTime)
{
    if (NULL == pTime) {
        return E_INVALID_ARGUMENT;
    }

    MemoryBuf_<sizeof(SystemTime)> timeBuf;
    ECode ec = NOERROR;

    timeBuf.Copy((Byte *)pTime, sizeof(SystemTime));
    if (NULL == g_pIRTC) {
        ec = CPseudoSyscall::FindRunningObject(L"device:rtc0",
                                         (PInterface *)&g_pIRTC);
        if (FAILED(ec)) return ec;
    }

    return g_pIRTC->Control(101, timeBuf, NULL, NULL);
}

CARAPI CPseudoKernel::System_QueryPerformanceCounter(
        /* [out] */ Int64 * pCounter)
{
    if (NULL == pCounter) {
        return E_INVALID_ARGUMENT;
    }

    return AuraSystem_QueryPerformanceCounter(pCounter);
}

CARAPI CPseudoKernel::System_QueryPerformanceFrequency(
        /* [out] */ Int64 * pFrequency)
{
    if (NULL == pFrequency) {
        return E_INVALID_ARGUMENT;
    }

    return AuraSystem_QueryPerformanceFrequency(pFrequency);
}

CARAPI CPseudoKernel::System_GetElapsedTime(
        /* [out] */ Millisecond32 * pTime)
{
    if (NULL == pTime) {
        return E_INVALID_ARGUMENT;
    }

    return AuraSystem_GetElapsedTime((Aura_Millisecond32 *)pTime);
}

CARAPI CPseudoKernel::System_GetIdleTime(
        /* [out] */ Millisecond32 * pTime)
{
    if (NULL == pTime) {
        return E_INVALID_ARGUMENT;
    }

    return AuraSystem_GetIdleTime((Aura_Millisecond32 *)pTime);
}

CARAPI CPseudoKernel::System_Reboot()
{
    // As the smartphone works in the only process, so to reboot the system
    // can be treat as to exit from it.
    CPseudoKernel::Process_ExitCurrent(0);
    assert(0);
    return E_NOT_IMPLEMENTED;
}

CARAPI CPseudoKernel::System_GetAllProcesses(
        /* [out] */ IObjectEnumerator ** ppProcesses)
{
    if (NULL == ppProcesses) {
        return E_INVALID_ARGUMENT;
    }

    CPseudoEnumeratorBuilder buider;
    return buider.BuildForProcess(ppProcesses);
}

CARAPI CPseudoKernel::System_GetMemorySizes(
        /* [out] */ MemorySize * pTotalPhysicalMemorySize,
        /* [out] */ MemorySize * pAvailablePhysicalMemorySize)
{
    if ((NULL == pTotalPhysicalMemorySize)
        && (NULL == pAvailablePhysicalMemorySize)) {
        return E_INVALID_ARGUMENT;
    }

    return AuraSystem_GetMemorySizes((Aura_Int32 *)pTotalPhysicalMemorySize,
                                 (Aura_Int32 *)pAvailablePhysicalMemorySize);
}

CHostingManager g_HostingManager;

CARAPI CPseudoKernel::System_GetHostingManager(
        /* [out] */ IHostingManager ** ppHostingManager)
{
    if (NULL == ppHostingManager) {
        return E_INVALID_ARGUMENT;
    }
    *ppHostingManager = (IHostingManager *)&g_HostingManager;
    return NOERROR;
}

CARAPI CPseudoKernel::System_TryWaitForAnyEvents(
        /* [in] */ const BufferOf<IEvent *> * pEvents,
        /* [in] */ Millisecond32 timeout,
        /* [out] */ WaitResult * pResult,
        /* [out] */ Int32 * pIndex,
        /* [out] */ EventState * pState)
{
    if (pEvents->IsNullOrEmpty()
      || NULL == pResult
      || NULL == pIndex) {
        return E_INVALID_ARGUMENT;
    }

    Int32 numberOfEvents = pEvents->GetUsed();
    if (0 == numberOfEvents
     || numberOfEvents > MAXIMUM_WAIT_EVENTS) {
        return E_INVALID_ARGUMENT;
    }

    return AuraSystem_TryWaitForAnyEvent((Aura_Int32)pEvents->GetUsed(),
                                 (Aura_Handle *)(pEvents->GetPayload()),
                                 (Aura_Int32)timeout,
                                 (Aura_WaitResult *)pResult,
                                 (Aura_Int32 *)pIndex,
                                 (Aura_EventState *)pState);
}

CARAPI CPseudoKernel::System_RequestIntrestedEvent(
        /* [in] */ SystemEvents intrestedEvents,
        /* [out] */ IEvent * * ppEvent)
{
    return  GetProcess()->RequestSystemEvent(intrestedEvents, ppEvent);
}

CARAPI CPseudoKernel::System_GetEnvironmentMutex(
        /* [out] */ IMutex ** ppEnvMutex)
{
    if (NULL == ppEnvMutex) {
        return E_INVALID_ARGUMENT;
    }

    return CMutex::S_Create(ppEnvMutex);
}

// --------------------------------------------------------

CARAPI CPseudoKernel::Process_CreateWithUnstarted(
        /* [out] */ IProcess ** ppProcess)
{
    IProcess * pProcess = NULL;
    ECode ec = NOERROR;

    if (NULL == ppProcess) {
        return E_INVALID_ARGUMENT;
    }

    pProcess = new CPseudoProcess();
    if (NULL == pProcess) {
        ec = E_OUT_OF_MEMORY;
        goto ErrorExit;
    }
    ec = ((CPseudoProcess *)pProcess)->Initialize();
    if (FAILED(ec)) {
        goto ErrorExit;
    }

    *ppProcess = pProcess;
    (*ppProcess)->AddRef();

    return NOERROR;

ErrorExit:
    if (NULL != pProcess) {
        delete pProcess;
        pProcess = NULL;
    }

    return ec;
}

CARAPI CPseudoKernel::Process_GetCurrent(
        /* [out] */ IProcess ** ppProcess)
{
    if (NULL == ppProcess) {
        return E_INVALID_ARGUMENT;
    }
    assert(NULL != s_pCurrentProcess);
    *ppProcess = s_pCurrentProcess;
    (*ppProcess)->AddRef();

    return NOERROR;
}

CARAPI CPseudoKernel::Process_GetCurrentId(
        /* [out] */ ProcessId * pProcessId)
{
    if (NULL == pProcessId) {
        return E_INVALID_ARGUMENT;
    }
    assert(AURA_INVALID_PID != s_currentProcessId);
    *pProcessId = s_currentProcessId;

    return NOERROR;
}

CARAPI CPseudoKernel::Process_ExitCurrent(
        /* [in] */ ExitCode exitCode)
{
    assert(NULL != s_pCurrentProcess);

    if (NULL != g_pIRTC) {
        g_pIRTC->Release();
        g_pIRTC = NULL;
    }
    GetProcess()->DoAtExit(exitCode);
    assert(0);
    return NOERROR;
}

CARAPI CPseudoKernel::Process_LoadModule(
        /* [in] */ WString name,
        /* [in] */ ModuleLoadFlags flags,
        /* [out] */ IModule ** ppModule)
{
    if (name.IsNullOrEmpty()
       || (NULL == ppModule)) {
        return E_INVALID_ARGUMENT;
    }

    return GetProcess()->LoadModule(name, flags, ppModule);
}

CARAPI CPseudoKernel::Process_FlushInstructionCache(
        /* [in] */ Address baseAddr,
        /* [in] */ MemorySize size)
{
    assert(0);
    return E_NOT_IMPLEMENTED;
}

// --------------------------------------------------------

CARAPI CPseudoKernel::Thread_Create(
        /* [in] */ Address threadMainStartup,
        /* [in] */ Address threadRoutine,
        /* [in] */ Address threadArg,
        /* [in] */ ThreadCreationFlags flags,
        /* [out] */ IThread ** ppThread)
{
    IThread * pThread = NULL;
    ECode ec = NOERROR;
    PInterface pCbContext = NULL;
    PInterface pApplet = NULL;
    PVoid pDomain = NULL;

    assert(NULL != threadMainStartup);
    if (NULL == threadRoutine) {
        return E_INVALID_ARGUMENT;
    }

    ec = CThread::S_Create(s_pCurrentProcess,
                            threadMainStartup,
                            threadRoutine, threadArg,
                            ThreadCreationFlag_Unstarted,
                            &pThread);
    if (FAILED(ec)) {
        return ec;
    }
    Tls_GetValue(ThreadLocalSlotType_Obj, TL_CALLBACK_SLOT, (PVoid*)&pCbContext);
    if (NULL != pCbContext) {
        pCbContext->AddRef();
        ((CThread*)pThread)->SetLocalSlotValue(TL_CALLBACK_SLOT, pCbContext);
    }
    Tls_GetValue(ThreadLocalSlotType_Obj, TL_APPLET_SLOT, (PVoid*)&pApplet);
    if (NULL != pApplet) {
        pApplet->AddRef();
        ((CThread*)pThread)->SetLocalSlotValue(TL_APPLET_SLOT, pApplet);
    }

    Tls_GetValue(ThreadLocalSlotType_Value, TL_DOMAIN_SLOT, &pDomain);
    ((CThread*)pThread)->SetLocalSlotValue(TL_DOMAIN_SLOT, pDomain);

    GetProcess()->AttachThread((CThread *)pThread);

    if (NULL != ppThread) {
        *ppThread = pThread;
    } else {
        pThread->Release();
    }

    if (ThreadCreationFlag_Unstarted != flags) {
        pThread->Start();
    }

    return NOERROR;
}

CARAPI CPseudoKernel::Thread_GetCurrent(
        /* [out] */ IThread ** ppThread)
{
    if (NULL == ppThread) {
        return E_INVALID_ARGUMENT;
    }

    *ppThread = GetCurrentThread_Expected();
    //BUGBUG: NULL in dllmain process detach
    if (*ppThread == NULL) return E_FAIL;
    (*ppThread)->AddRef();

    return NOERROR;
}

CARAPI CPseudoKernel::Thread_GetCurrentId(
        /* [out] */ ThreadId * pThreadId)
{
    if (NULL == pThreadId) {
        return E_INVALID_ARGUMENT;
    }
    *pThreadId = AuraThread_GetCurrentId();
    return NOERROR;
}

CARAPI CPseudoKernel::Thread_CurrentIsMain(
        /* [out] */ Boolean * pMainThread)
{
    IThread * pThread = NULL;

    if (NULL == pMainThread) {
        return E_INVALID_ARGUMENT;
    }

    pThread =  GetCurrentThread_Expected();
    *pMainThread = (s_pMainThread == pThread) ? TRUE : FALSE;

    return NOERROR;
}

CARAPI CPseudoKernel::Thread_QuitCurrent(
        /* [in] */ QuitCode quitCode)
{
    IThread * pThread = NULL;

    pThread = GetCurrentThread_Expected();
    if (::IsMainThread(pThread)) {
        ((CProcess *)s_pCurrentProcess)->DoAtExit(quitCode);
    }
    else {
        ((CProcess *)s_pCurrentProcess)->DetachThread((CThread *)pThread);
        ((CThread *)pThread)->DoAtQuit(quitCode, FALSE);
         _Elastos_SequencedContext_Leave();
        AuraTls_SetValue((Aura_UInt32)s_tlsCurrentThreadIndex, (Aura_PVoid *)AURA_NULL);
        pThread->Release();
        AuraThread_Quit((Aura_QuitCode)quitCode);
    }

    assert(0);
    return NOERROR;
}

CARAPI CPseudoKernel::Thread_Sleep(
        /* [in] */ Millisecond32 period,
        /* [out] */ WaitResult * pResult)
{
    WaitResult wr;

    if (0 == period) {
        AuraThread_Sleep(0, (Aura_WaitResult *)&wr);
        return NOERROR;
    }

    THREAD_START_SLEEP()
    {
        AuraThread_Sleep(period, (Aura_WaitResult *)&wr);
    }
    THREAD_END_SLEEP;

    if (NULL != pResult) {
        *pResult = wr;
    }
    return NOERROR;
}

CARAPI CPseudoKernel::Thread_Yield()
{
    AuraThread_Yield();
    return NOERROR;
}

// --------------------------------------------------------

CARAPI CPseudoKernel::VirtualMemory_Map(
        /* [in] */ Address startingAddr,
        /* [in] */ MemorySize size,
        /* [in] */ MemoryMapFlags flags,
        /* [in] */ MemoryProtection protect,
        /* [out] */ Address *pSettledAddr)
{
    if ((size <= 0)
        || !IS_PAGE_ALIGNED(startingAddr)
        || !IS_PAGE_ALIGNED(size)
        || (NULL == pSettledAddr)
        || ((flags & MemoryMap_UpGrow)
         && (flags & MemoryMap_DownGrow))) {
        return E_INVALID_ARGUMENT;
    }

    return AuraVirtualMemory_Map(startingAddr,
                            (Aura_MemorySize)size,
                            (Aura_MemoryMapFlags)flags,
                            (Aura_MemoryProtection)protect,
                            (Aura_Address *)pSettledAddr);
}

CARAPI CPseudoKernel::VirtualMemory_Query(
        /* [in] */ Address address,
        /* [out] */ Address *pBaseAddr,
        /* [out] */ MemorySize *pSize)
{
    if ((NULL == pBaseAddr)
        && (NULL == pSize)) {
        return E_INVALID_ARGUMENT;
    }

    return AuraVirtualMemory_Query(address,
                            (Aura_Address *)pBaseAddr,
                            (Aura_MemorySize *)pSize);
}

CARAPI CPseudoKernel::VirtualMemory_SetProtection(
        /* [in] */ Address baseAddr,
        /* [in] */ MemorySize size,
        /* [in] */ MemoryProtection protect)
{
    if (size <= 0) {
        return E_INVALID_ARGUMENT;
    }

    return AuraVirtualMemory_SetProtection(baseAddr, size, protect);
}

CARAPI CPseudoKernel::VirtualMemory_CheckProtection(
        /* [in] */ Address address,
        /* [in] */ MemoryProtection protect,
        /* [out] */ Boolean *pValid)
{
    if (NULL == pValid) {
        return E_INVALID_ARGUMENT;
    }

    return AuraVirtualMemory_CheckProtection(address, protect, pValid);
}

CARAPI CPseudoKernel::VirtualMemory_Commit(
        /* [in] */ Address address)
{

    return AuraVirtualMemory_Commit(address);
}

CARAPI CPseudoKernel::VirtualMemory_IoRemap(
        /* [in] */ Address startingAddr,
        /* [in] */ MemorySize size,
        /* [in] */ Address physicalAddr,
        /* [in] */ MemoryMapFlags flags,
        /* [in] */ MemoryProtection protect,
        /* [out] */ Address* pSettledAddr)
{
    assert(0);
    return E_INVALID_ARGUMENT;
}

CARAPI CPseudoKernel::VirtualMemory_Unmap(
        /* [in] */ Address baseAddr,
        /* [in] */ MemorySize size)
{
    if (size <= 0) {
        return E_INVALID_ARGUMENT;
    }

    return AuraVirtualMemory_Unmap(baseAddr, size);
}

// --------------------------------------------------------

CARAPI CPseudoKernel::Mutex_Create(
        /* [out] */ IMutex ** ppMutex)
{
    if (NULL == ppMutex) {
        return E_INVALID_ARGUMENT;
    }

    return CMutex::S_Create(ppMutex);
}

CARAPI CPseudoKernel::Mutex_Create(
        /* [in] */ WString name,
        /* [out] */ IMutex ** ppMutex,
        /* [out] */ Boolean * pAlreadyExisted)
{
    Boolean bAlreadyExisted = FALSE;
    ECode ec = NOERROR;

    if (name.IsNullOrEmpty() || (NULL == ppMutex)) {
        return E_INVALID_ARGUMENT;
    }

    CNamedMutexFactory factory(name);
    NamedObject * pNamedObj = NULL;
    ec = NamedObject::S_CreateObject(&factory, &pNamedObj, &bAlreadyExisted);
    if (FAILED(ec)) {
        return ec;
    }

    *ppMutex = (IMutex *)pNamedObj->GetObject();
    if (NULL != pAlreadyExisted) {
        *pAlreadyExisted = bAlreadyExisted;
    }

    return ec;
}

CARAPI CPseudoKernel::Event_Create(
        /* [in] */ Boolean manualReset,
        /* [in] */ EventState initialState,
        /* [out] */ IEvent ** ppEvent)
{
    if (NULL == ppEvent) {
        return E_INVALID_ARGUMENT;
    }

    return CEvent::S_Create(manualReset, initialState, ppEvent);
}

CARAPI CPseudoKernel::Event_Create(
        /* [in] */ WString name,
        /* [in] */ Boolean manualReset,
        /* [in] */ EventState initialState,
        /* [out] */ IEvent ** ppEvent,
        /* [out] */ Boolean * pAlreadyExisted)
{
    Boolean bAlreadyExisted = FALSE;
    ECode ec = NOERROR;

    if (name.IsNullOrEmpty() || (NULL == ppEvent)) {
        return E_INVALID_ARGUMENT;
    }

    CNamedEventFactory factory(name, manualReset, initialState);
    NamedObject * pNamedObj = NULL;
    ec = NamedObject::S_CreateObject(&factory, &pNamedObj, &bAlreadyExisted);
    if (FAILED(ec)) {
        return ec;
    }

    *ppEvent = (IEvent *)pNamedObj->GetObject();
    if (NULL != pAlreadyExisted) {
        *pAlreadyExisted = bAlreadyExisted;
    }
    return ec;
}

CARAPI CPseudoKernel::Condition_Create(
        /* [out] */ ICondition ** ppCondition)
{
    if (NULL == ppCondition) {
        return E_INVALID_ARGUMENT;
    }

    return CCondition::S_Create(ppCondition);
}

CARAPI CPseudoKernel::Condition_Create(
        /* [in] */ WString name,
        /* [out] */ ICondition ** ppCondition,
        /* [out] */ Boolean * pAlreadyExisted)
{
    Boolean bAlreadyExisted = FALSE;
    ECode ec = NOERROR;

    if (name.IsNullOrEmpty() || (NULL == ppCondition)) {
        return E_INVALID_ARGUMENT;
    }

    CNamedConditionFactory factory(name);
    NamedObject * pNamedObj = NULL;
    ec = NamedObject::S_CreateObject(&factory, &pNamedObj, &bAlreadyExisted);
    if (FAILED(ec)) {
        return ec;
    }

    *ppCondition = (ICondition *)pNamedObj->GetObject();
    if (NULL != pAlreadyExisted) {
        *pAlreadyExisted = bAlreadyExisted;
    }
    return ec;
}

CARAPI CPseudoKernel::ReaderWriterLock_Create(
        /* [out] */ IReaderWriterLock ** ppRwlock)
{
    if (NULL == ppRwlock) {
        return E_INVALID_ARGUMENT;
    }
    return CReaderWriterLock::S_Create(ppRwlock);
}

CARAPI CPseudoKernel::ReaderWriterLock_Create(
        /* [in] */ WString name,
        /* [out] */ IReaderWriterLock ** ppRwlock,
        /* [out] */ Boolean * pAlreadyExisted)
{
    assert(0);
    return E_INVALID_ARGUMENT;
}

CARAPI CPseudoKernel::SharedMemory_Create(
        /* [in] */ WString name,
        /* [in] */ MemorySize size,
        /* [in] */ Boolean commit,
        /* [out] */ ISharedMemory ** ppSharedMemory,
        /* [out] */ Boolean * pAlreadyExisted)
{
    Boolean bAlreadyExisted = FALSE;
    ECode ec = NOERROR;

    if (name.IsNullOrEmpty() || (NULL == ppSharedMemory)) {
        return E_INVALID_ARGUMENT;
    }

    CSharedMemoryFactory factory(name, size, commit);
    NamedObject * pNamedObj = NULL;
    ec = NamedObject::S_CreateObject(&factory, &pNamedObj, &bAlreadyExisted);
    if (FAILED(ec)) {
        return ec;
    }
    *ppSharedMemory = (ISharedMemory *)pNamedObj->GetObject();
    if (NULL != pAlreadyExisted) {
        *pAlreadyExisted = bAlreadyExisted;
    }

    return ec;
}

// --------------------------------------------------------
CARAPI CPseudoKernel::Tls_AcquireSlot(
        /* [in] */ ThreadLocalSlotType type,
        /* [out] */ Int32 * pSlotIndex)
{
    assert(NULL != s_pCurrentProcess);
    return GetProcess()->AcquireThreadLocalSlot(type, pSlotIndex);
}

CARAPI CPseudoKernel::Tls_RelinquishSlot(
        /* [in] */ Int32 slotIndex,
        /* [out] */ BufferOf<Address> * pUsedPtrs)
{
    assert(NULL != s_pCurrentProcess);
    return GetProcess()->RelinquishThreadLocalSlot(slotIndex, pUsedPtrs);
}

CARAPI CPseudoKernel::Tls_CleanupSlot(
        /* [in] */ Int32 slotIndex,
        /* [out] */ BufferOf<Address> * pUsedPtrs)
{
    assert(NULL != s_pCurrentProcess);
    return GetProcess()->CleanUpThreadLocalSlot(slotIndex, pUsedPtrs);
}

CARAPI CPseudoKernel::Tls_GetValue(
        /* [in] */ ThreadLocalSlotType type,
        /* [in] */ Int32 slotIndex,
        /* [out] */ PVoid * ppValue)
{
    assert(NULL != s_pCurrentProcess);
    return GetProcess()->GetThreadLocalSlotValue(type, slotIndex, ppValue);
}

CARAPI CPseudoKernel::Tls_SetValue(
        /* [in] */ ThreadLocalSlotType type,
        /* [in] */ Int32 slotIndex,
        /* [in] */ PVoid pValue)
{
    assert(NULL != s_pCurrentProcess);
    return GetProcess()->SetThreadLocalSlotValue(type, slotIndex, pValue);
}

// --------------------------------------------------------

CARAPI CPseudoKernel::SystemEvent_Create(
        /* [out] */ PVoid * phSysEvent)
{
    if (NULL == phSysEvent) {
        return E_INVALID_ARGUMENT;
    }

    return AuraEvent_Create(AURA_FALSE, AURA_UNSIGNALED, phSysEvent);
}

CARAPI CPseudoKernel::SystemEvent_Wait(
        /* [in] */ PVoid hSysEvent)
{
    CThread * pThread = NULL;
    ECode ec = NOERROR;
    WaitResult wr;

    assert(NULL != hSysEvent);

    pThread = (CThread *)GetCurrentThread_Unexpected();
    if (NULL != pThread) {
        pThread->SetThreadState(ThreadState_Sleeping);
    }
    ec = AuraEvent_Wait(hSysEvent,
                        AURA_INFINITE,
                        (Aura_WaitResult *)&wr,
                        AURA_NULL);
    if (NULL != pThread) {
        pThread->SetThreadState(ThreadState_Running);
    }

    return ec;
}

CARAPI CPseudoKernel::SystemEvent_Notify(
        /* [in] */ PVoid hSysEvent)
{
    assert(NULL != hSysEvent);
    return AuraEvent_Signal(hSysEvent, AURA_SIGNALED);
}

CARAPI CPseudoKernel::SystemEvent_Destroy(
        /* [in] */ PVoid hSysEvent)
{
    assert(NULL != hSysEvent);
    return AuraEvent_Destroy(hSysEvent);
}

